package com.neuedu.corejava.jdbc1.dao.impl;

import java.sql.Connection;

import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;

//import javax.jws.soap.SOAPBinding.Use;

import com.neuedu.corejava.jdbc1.bean.Users;
import com.neuedu.corejava.jdbc1.DBHelper;
import com.neuedu.corejava.jdbc1.dao.IUsersDao;

/**
 * 20190809
 * @author admin
 *
 */
public class IUsersDaoImpl implements IUsersDao {

	@Override
	public boolean add(Users param) {
		// TODO Auto-generated method stub
		Connection conn=DBHelper.openConnection();
		PreparedStatement stmt=null;
	
		try {
			String sql="insert into users(id, name, age, birthdate) values(SEQ_USERS.NEXTVAL,?,?,?)";
			stmt=conn.prepareStatement(sql);
			stmt.setString(1, param.getName());
			stmt.setInt(2, param.getAge());
			//参数值是java.sql.Date;只能保存年月日，这里一般需要把util.Date转换为sql.Date
			//stmt.setDate(3, new java.sql.Date(param.getBirthDate().getTime()));
			//参数值是java.sql.Date,只能保存时分秒；这里一般需要把util.Time转换为sql.Time
			//stmt.setTime(3, new java.sql.Time(param.getBirthDate().getTime()));
			
			//参数值是java.sql.Timestamp，只能保存年月日时分秒;这里一般需要把util.Date转换为sql.Date.Timestamp
			stmt.setTimestamp(3, new java.sql.Timestamp(param.getBirthDate().getTime()));
			
			int count=stmt.executeUpdate();//executeUpdate会返回sql更新数据时更新了多少行，更新行数
			if(count==1){
				//更新成功，返回true--在项目中注释不能写语法，要写业务说明
				return true;//一个方法内部可有多个return//在try catch 中有return，finally照常执行
			}
			
			
		} catch (SQLException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}finally{
			DBHelper.closeAll(null, stmt, conn);
		}
		
		return false;
	}

	@Override
	public boolean edit(Users param) {
		// TODO Auto-generated method stub
		Connection conn=DBHelper.openConnection();
		PreparedStatement stmt=null;
	
		try {
			//根据主键修改年龄和出生日期,主键和账号不能修改
			String sql="update users set age=?,birthdate=? where id=?";
			stmt=conn.prepareStatement(sql);
			stmt.setInt(3, param.getId());
			stmt.setInt(1, param.getAge());
			//参数值是java.sql.Date;只能保存年月日，这里一般需要把util.Date转换为sql.Date
			//stmt.setDate(3, new java.sql.Date(param.getBirthDate().getTime()));
			//参数值是java.sql.Date,只能保存时分秒；这里一般需要把util.Time转换为sql.Time
			//stmt.setTime(3, new java.sql.Time(param.getBirthDate().getTime()));
			
			//参数值是java.sql.Timestamp，只能保存年月日时分秒;这里一般需要把util.Date转换为sql.Date.Timestamp
			stmt.setTimestamp(2, new java.sql.Timestamp(param.getBirthDate().getTime()));
			
			int count=stmt.executeUpdate();//executeUpdate会返回sql更新数据时更新了多少行，更新行数
			if(count==1){
				//更新成功，返回true--在项目中注释不能写语法，要写业务说明
				return true;//一个方法内部可有多个return//在try catch 中有return，finally照常执行
			}
			
			
		} catch (SQLException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}finally{
			DBHelper.closeAll(null, stmt, conn);
		}
		
		return false;
	}

	@Override
	public boolean deleteById(int id) {
		// TODO Auto-generated method stub
		Connection conn=DBHelper.openConnection();
		PreparedStatement stmt=null;
	
		try {
			//根据主键删除数据
			String sql="delete from users where id=?";
			stmt=conn.prepareStatement(sql);
			stmt.setInt(1,id);
			int count=stmt.executeUpdate();//executeUpdate会返回sql更新数据时更新了多少行，更新行数
			if(count==1){
				//更新成功，返回true--在项目中注释不能写语法，要写业务说明
				return true;//一个方法内部可有多个return//在try catch 中有return，finally照常执行
			}
			
			
		} catch (SQLException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}finally{
			DBHelper.closeAll(null, stmt, conn);
		}
		
		return false;
	}

	@Override
	public Users findById(int id) {
		// TODO Auto-generated method stub
		Users users = null;
		// 1.注册驱动2.建立connection连接
		Connection conn = DBHelper.openConnection();
		PreparedStatement stmt = null;// 可以防止sql注入攻击,在批量更新时具有更好的性能
		ResultSet rs = null;
		try {
			// 3.打开状态连接
			String sql = "select id,name name1,age,birthdate from users where id=?";
			stmt = conn.prepareStatement(sql);
			// 4.执行sql
			stmt.setInt(1, id);
			rs = stmt.executeQuery();
			// 5.对sql执行结果进行处理
			if (rs.next()) {//根据主键或唯一键查询数据，要么有一条数据，要么没有数据。可以使用if进行判断
				int id0 = rs.getInt(1);// 可以根据列的序号获取列的数据，列的序号是从1开始的，1表示第一列
				String name = rs.getString("name1");// 可以根据列名或列的别名获取列的数据 (有别名用别名，没别名用列名)
				int age = rs.getInt("age");
				Date birthDate = rs.getTimestamp("birthdate");
				users = new Users(id0, name, age, birthDate);
			}
		} catch (SQLException e) {
			e.printStackTrace();
		} finally {
			// 6.关闭连接，是否资源
			DBHelper.closeAll(rs, stmt, conn);
		}
		return users;

	}

	@Override
	public List<Users> findByAll() {
		// TODO Auto-generated method stub
		List<Users> list = new ArrayList<>();
		// 1.注册驱动2.建立connection连接
		//Connection conn = DBHelper.openConnection();
		Connection conn = DBHelper.openConnection();
		// Statement statement;//可能造成sql注入攻击
		PreparedStatement stmt = null;// 可以防止sql注入攻击,在批量更新时具有更好的性能
		ResultSet rs = null;
		// statement = conn.createStatement();
		try {
			//3.打开状态连接
			String sql = "select id,name,age,birthdate from users";
			stmt = conn.prepareStatement(sql);
			//4.执行sql
			rs = stmt.executeQuery();
			//5.对sql执行结果进行处理
			while(rs.next()) {//next()方法从结果集中取出一行数据，如果有数据返回true，没有数据返回false
				int id = rs.getInt(1);//可以根据列的序号获取列的数据，列的序号是从1开始的，1表示第一列
				String name = rs.getString("name");//可以根据列名或列的别名获取列的数据 (有别名用别名，没别名用列名)
				int  age = rs.getInt("age");
				
				//getTimestamp,返回java.sql.Timestamp,Timestamp是java.util.Date的子类，可以保存： 年月日 时分秒毫秒
				Date birthDate = rs.getTimestamp("birthdate");
				
				//getDate,返回java.sql.Date,sql.Date是java.util.Date的子类，可以保存： 年月日 
				//birthDate = rs.getDate("birthdate");//入学日期，入职日期
				//getTime,返回java.sql.Time,sql.Time是java.util.Date的子类，可以保存： 时分秒 
				//birthDate = rs.getTime("birthdate");//班车发车时刻表，飞机的飞行时刻表
				
				Users users = new Users(id, name, age, birthDate);
				list.add(users);
			}	
		} catch (SQLException e) {
			e.printStackTrace();
		}finally {
			//6.关闭连接，是否资源
			DBHelper.closeAll(rs, stmt, conn);
		}
		return list;

	}

	@Override
	public List<Users> findByExample(Users param) {//根据账号进行模糊查询
		// TODO Auto-generated method stub
		List<Users> list = new ArrayList<>();
		// 1.注册驱动2.建立connection连接
		//Connection conn = DBHelper.openConnection();
		Connection conn = DBHelper.openConnection();
		// Statement statement;//可能造成sql注入攻击
		PreparedStatement stmt = null;// 可以防止sql注入攻击,在批量更新时具有更好的性能
		ResultSet rs = null;
		// statement = conn.createStatement();
		try {
			//3.打开状态连接
			//编写sql时，如果需要传递参数，使用？进行占位
			String sql = "select id,name,age,birthdate from users where name like ?";//注意不要拼接sql
			stmt = conn.prepareStatement(sql);
			//4.执行sql
			//如果sql有参数，即有？号，需要进行参数填充
			stmt.setString(1, "%"+param.getName()+"%");//参数的序号是从1开始的，1表示第一个参数
			rs=stmt.executeQuery();
			//5.对sql执行结果进行处理
			while(rs.next()) {//next()方法从结果集中取出一行数据，如果有数据返回true，没有数据返回false
				int id = rs.getInt(1);//可以根据列的序号获取列的数据，列的序号是从1开始的，1表示第一列
				String name = rs.getString("name");//可以根据列名或列的别名获取列的数据 (有别名用别名，没别名用列名)
				int  age = rs.getInt("age");
				
				//getTimestamp,返回java.sql.Timestamp,Timestamp是java.util.Date的子类，可以保存： 年月日 时分秒毫秒
				Date birthDate = rs.getTimestamp("birthdate");
				
				//getDate,返回java.sql.Date,sql.Date是java.util.Date的子类，可以保存： 年月日 
				//birthDate = rs.getDate("birthdate");//入学日期，入职日期
				//getTime,返回java.sql.Time,sql.Time是java.util.Date的子类，可以保存： 时分秒 
				//birthDate = rs.getTime("birthdate");//班车发车时刻表，飞机的飞行时刻表
				
				Users users = new Users(id, name, age, birthDate);
				list.add(users);
			}	
		} catch (SQLException e) {
			e.printStackTrace();
		}finally {
			//6.关闭连接，是否资源
			DBHelper.closeAll(rs, stmt, conn);
		}
		return list;
	}

	@Override
	public List<Users> findByPage(int page, int size) {
		// TODO Auto-generated method stub
		List<Users> list = new ArrayList<>();
		// 1.注册驱动2.建立connection连接
		//Connection conn = DBHelper.openConnection();
		Connection conn = DBHelper.openConnection();
		// Statement statement;//可能造成sql注入攻击
		PreparedStatement stmt = null;// 可以防止sql注入攻击,在批量更新时具有更好的性能
		ResultSet rs = null;
		// statement = conn.createStatement();
		try {
			//3.打开状态连接
			//编写sql时，如果需要传递参数，使用？进行占位
			String sql = "select * from "+
					"(select rownum rn,id,name,age,birthdate from users where rownum<=?) where rn>?";//注意不要拼接sql
			stmt = conn.prepareStatement(sql);
			//4.执行sql
			//如果sql有参数，即有？号，需要进行参数填充
			stmt.setInt(1, page*size);//参数的序号是从1开始的，1表示第一个参数
			stmt.setInt(2, (page-1)*size);
			
			rs=stmt.executeQuery();
			//5.对sql执行结果进行处理
			while(rs.next()) {//next()方法从结果集中取出一行数据，如果有数据返回true，没有数据返回false
				int id = rs.getInt(2);//可以根据列的序号获取列的数据，列的序号是从1开始的，1表示第一列
				String name = rs.getString("name");//可以根据列名或列的别名获取列的数据 (有别名用别名，没别名用列名)
				int  age = rs.getInt("age");
				
				//getTimestamp,返回java.sql.Timestamp,Timestamp是java.util.Date的子类，可以保存： 年月日 时分秒毫秒
				Date birthDate = rs.getTimestamp("birthdate");
				
				//getDate,返回java.sql.Date,sql.Date是java.util.Date的子类，可以保存： 年月日 
				//birthDate = rs.getDate("birthdate");//入学日期，入职日期
				//getTime,返回java.sql.Time,sql.Time是java.util.Date的子类，可以保存： 时分秒 
				//birthDate = rs.getTime("birthdate");//班车发车时刻表，飞机的飞行时刻表
				
				Users users = new Users(id, name, age, birthDate);
				list.add(users);
			}	
		} catch (SQLException e) {
			e.printStackTrace();
		}finally {
			//6.关闭连接，是否资源
			DBHelper.closeAll(rs, stmt, conn);
		}
		return list;
	}

	@Override
	public int deleteByIds(int[] ids) {
		// TODO Auto-generated method stub
		int result=0;
		Connection conn=DBHelper.openConnection();
		PreparedStatement stmt=null;
		
		//业务说明：批量删除数据，只要有一条删除失败，则所有的都不删除
		try {
			conn.setAutoCommit(false);//关闭自动提交，开启数据库事务
			String sql="delete from users where id=?";
			stmt=conn.prepareStatement(sql);
			//
			for(int id:ids){
				stmt.setInt(1, id);
				stmt.addBatch();//批量发送，每循环一次就是一批数据
			}
			int[] counts=stmt.executeBatch();//返回一个数组，保存了每批数据更新的情况，每批数更新的数量（1或0）
			for(int i:counts){//统计有多少批数据删除成功
				if(i==1){
					result++;
				}
			}
			if(result==ids.length){
				conn.commit();//提交事务
				conn.setAutoCommit(true);//开启（还原）数据库
			}else{
				conn.rollback();//回滚事务
			}
		} catch (SQLException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			if(conn!=null){//删除数据，如有不符删除异常，则需要全部回滚
				try {
					conn.rollback();
					conn.setAutoCommit(true);
				} catch (SQLException e1) {
					// TODO Auto-generated catch block
					e1.printStackTrace();
				}
			}
		}finally{
			DBHelper.closeAll(null, stmt, conn);
		}
		return result;
	}

	@Override
	public int addAll(List<Users> users) {
		// TODO Auto-generated method stub
		return 0;
	}

	@Override
	public int editAll(List<Users> users) {
		// TODO Auto-generated method stub
		return 0;
	}

	
}
